/**
 * @p.md
 * 
 * DefaultActorProcess 类，实现 Actor 进程的默认行为
 */
import { PID } from './pid';
import { Process, createTerminatedMessage, isWatch, isUnwatch, isStop, isRestart } from './process';
import { Actor } from './actor';
import { ActorSystem } from './actorSystem';
import { Props } from './props';
import { Mailbox, DefaultMessageQueue } from './mailbox';
import { MessageInvoker } from './messageInvoker';
import { Dispatcher, Dispatchers } from './dispatcher';
import { SupervisorDirective, Supervisor } from './supervisorDirective';
import { createDefaultMailbox } from './mailboxFactory';
import { Context, InfoPart, BasePart, MessagePart, SenderPart, ReceiverPart, SpawnerPart, StopperPart } from './context';
import { EventStream, Events } from './eventStream';

interface ExtendedActor extends Actor {
  supervisor?: Supervisor;
  parent?: PID;
  pid?: PID;
  preRestart?(): void;
  postRestart?(): void;
  postStop?(): void;
  receiveSystemMessage?(message: any): void;
}

class ActorContext implements Context {
  constructor(
    private readonly _actor: ExtendedActor,
    private readonly _message: any,
    private readonly _system: ActorSystem
  ) {}

  // InfoPart
  parent(): PID | null {
    return this._actor.parent || null;
  }

  self(): PID {
    return this._actor.pid!;
  }

  actor(): Actor {
    return this._actor;
  }

  actorSystem(): ActorSystem {
    return this._system;
  }

  // MessagePart
  message(): any {
    return this._message;
  }

  // Other interface implementations would go here
  // For now, we'll implement minimal stubs
  
  // BasePart
  receiveTimeout(): number { return 0; }
  children(): PID[] { return []; }
  respond(response: any): void {}
  stash(): void {}
  watch(pid: PID): void {}
  unwatch(pid: PID): void {}
  setReceiveTimeout(duration: number): void {}
  cancelReceiveTimeout(): void {}
  forward(pid: PID): void {}
  reenterAfter(future: any, continuation: any): void {}

  // SenderPart
  send(target: PID, message: any): void {
    this._system.root.send(target, message);
  }
  
  request(target: PID, message: any): void {
    this._system.root.request(target, message);
  }
  
  requestFuture(target: PID, message: any, timeout: number): any { 
    return this._system.root.requestFuture(target, message, timeout);
  }

  // ReceiverPart
  sender(): PID | undefined { return undefined; }

  // SpawnerPart
  spawn(props: Props): PID { 
    return this._system.root.spawn(props);
  }
  
  spawnNamed(props: Props, name: string): PID { 
    return this._system.root.spawnNamed(props, name);
  }
  
  spawnPrefix(props: Props, prefix: string): PID { 
    return this._system.root.spawnPrefix(props, prefix);
  }

  // StopperPart
  stop(pid: PID): void {
    this._system.root.stop(pid);
  }
}

/**
 * 默认 Actor 进程实现
 */
export class DefaultActorProcess implements Process, MessageInvoker {
  // Actor 实例
  private _actor: Actor;
  // Actor 系统实例
  private readonly _system: ActorSystem;
  // Actor PID
  private readonly _self: PID;
  // 监视此 Actor 的 PID 列表
  private readonly _watchers: Set<string> = new Set();
  // Actor 邮箱
  private readonly _mailbox: Mailbox;
  // Actor 配置
  private readonly _props: Props;
  // 调度器
  private readonly _dispatcher: Dispatcher;
  // 是否已停止
  private _stopped: boolean = false;
  // 重启计数
  private _restartCount: number = 0;
  private messageQueue: DefaultMessageQueue;
  private systemMessageQueue: DefaultMessageQueue;
  private dispatcher: Dispatcher;
  private actorMap: Map<string, ExtendedActor>;
  private eventStream: EventStream;
  
  /**
   * 构造函数
   * @param actor Actor 实例
   * @param props Actor 配置
   * @param system Actor 系统实例
   * @param self Actor PID
   */
  constructor(actor: Actor, props: Props, system: ActorSystem, self: PID) {
    this._actor = actor;
    this._props = props;
    this._system = system;
    this._self = self;
    
    // 初始化actorMap
    this.actorMap = new Map();
    
    // 初始化事件流
    this.eventStream = system.eventStream;
    
    // 获取调度器，如果未配置则使用默认调度器
    this._dispatcher = props.dispatcher || Dispatchers.synchronous();
    
    // 创建邮箱
    this._mailbox = props.mailboxProducer ? 
      props.mailboxProducer() : 
      createDefaultMailbox();
    
    // 设置扩展信息
    if (this._actor as ExtendedActor) {
      const extendedActor = this._actor as ExtendedActor;
      extendedActor.pid = self;
      this.actorMap.set(self.id, extendedActor);
    }
    
    // 初始化队列
    this.messageQueue = new DefaultMessageQueue();
    this.systemMessageQueue = new DefaultMessageQueue();
    this.dispatcher = Dispatchers.synchronous();
    
    // 注册消息处理器
    this._mailbox.registerHandlers(this, this._dispatcher);
    
    // 发布Actor启动事件
    this.eventStream.publish(new Events.ActorStarted(self));
    
    // 启动邮箱
    this._mailbox.start();
  }
  
  /**
   * 获取调用者的唯一标识
   */
  id(): string {
    return this._self.id;
  }
  
  /**
   * 发送用户消息
   */
  sendUserMessage(pid: PID, message: any): void {
    if (this._stopped) {
      return;
    }
    
    this._mailbox.postMessage(message);
  }
  
  /**
   * 处理系统消息
   * @param pid 目标 PID
   * @param message 系统消息
   */
  sendSystemMessage(pid: PID, message: any): void {
    this._mailbox.postSystemMessage(message);
  }
  
  /**
   * 停止 Actor 进程
   * @param pid 目标 PID
   */
  stop(pid: PID): void {
    if (this._stopped) {
      return;
    }
    
    this._stopped = true;
    
    // 通知监视者
    this.notifyWatchers();
    
    // 发布停止事件
    if (this._self) {
      this.eventStream.publish(new Events.ActorStopped(this._self));
    }
    
    // 如果Actor实现了postStop方法，调用它
    const extendedActor = this._actor as ExtendedActor;
    if (extendedActor.postStop) {
      extendedActor.postStop();
    }
    
    // 从进程注册表中移除
    this._system.processRegistry.remove(pid);
  }
  
  /**
   * 通知所有监视者此 Actor 已终止
   */
  private notifyWatchers(): void {
    if (this._watchers.size === 0) {
      return;
    }
    
    const terminated = createTerminatedMessage(this._self);
    
    for (const watcherStr of this._watchers) {
      const [address, id] = watcherStr.split('@');
      const watcher = new PID(address, id);
      
      const process = this._system.processRegistry.get(watcher);
      if (process) {
        process.sendSystemMessage(watcher, terminated);
      }
    }
    
    this._watchers.clear();
  }
  
  /**
   * 调用用户消息处理
   * @param actor 目标 Actor
   * @param message 用户消息
   */
  invokeUserMessage(actor: ExtendedActor, message: any): void {
    try {
      // 处理信封消息，提取实际消息内容和发送者
      let messageContent = message;
      let sender: PID | undefined;
      
      if (message && typeof message === 'object' && 'message' in message && 'sender' in message) {
        messageContent = message.message;
        sender = message.sender;
      }
      
      // 将函数类型的消息转换为对象格式
      if (typeof messageContent === 'function') {
        console.warn(`Warning: Message sent to ${actor.pid?.toString() || 'actor'} is a function reference. Converting to object.`);
        messageContent = {
          type: 'FunctionMessage',
          name: messageContent.name || 'anonymous',
          description: '函数引用已转换为对象格式',
          originalType: typeof messageContent
        };
      }
      
      // 直接使用自定义上下文创建和处理
      const context = {
        // InfoPart
        parent: () => null,
        self: () => this._self,
        actor: () => actor,
        actorSystem: () => this._system,
        
        // MessagePart - 关键部分，直接返回处理过的消息内容
        message: () => messageContent,
        
        // ReceiverPart
        sender: () => sender,
        
        // 其他必要的部分实现
        send: (target: PID, msg: any) => this._system.root.send(target, msg),
        request: (target: PID, msg: any) => this._system.root.request(target, msg),
        requestFuture: (target: PID, msg: any, timeout: number) => this._system.root.requestFuture(target, msg, timeout),
        
        // 其他方法的最小实现
        receiveTimeout: () => 0,
        children: () => [],
        respond: (response: any) => {},
        stash: () => {},
        watch: (pid: PID) => {},
        unwatch: (pid: PID) => {},
        setReceiveTimeout: (duration: number) => {},
        cancelReceiveTimeout: () => {},
        forward: (pid: PID) => {},
        reenterAfter: (future: any, continuation: any) => {},
        spawn: (props: Props) => this._system.root.spawn(props),
        spawnNamed: (props: Props, name: string) => this._system.root.spawnNamed(props, name),
        spawnPrefix: (props: Props, prefix: string) => this._system.root.spawnPrefix(props, prefix),
        stop: (pid: PID) => this._system.root.stop(pid)
      };
      
      // 调用Actor的receive方法
      actor.receive(context);
    } catch (error) {
      this.escalateFailure(actor, error);
    }
  }
  
  /**
   * 调用系统消息处理
   * @param actor 目标 Actor
   * @param context 上下文
   * @param message 系统消息
   */
  invokeSystemMessage(actor: ExtendedActor, message: any): void {
    if (actor.receiveSystemMessage) {
      try {
        actor.receiveSystemMessage(message);
      } catch (error) {
        this.escalateFailure(actor, error);
      }
    }
  }
  
  /**
   * 将错误升级到监督系统处理
   * @param actor 目标 Actor
   * @param reason 错误原因
   */
  escalateFailure(actor: ExtendedActor, reason: any): void {
    const directive = this._props.supervisor?.handleFailure(this._self, reason) || SupervisorDirective.Restart;
    
    switch (directive) {
      case SupervisorDirective.Resume:
        break;
      case SupervisorDirective.Restart:
        this.restartActor(reason instanceof Error ? reason : new Error(String(reason)));
        break;
      case SupervisorDirective.Stop:
        this.stop(this._self);
        break;
      case SupervisorDirective.Escalate:
        console.warn(`[Actor] Error escalated for ${this._self.id}`, reason);
        break;
    }
  }
  
  /**
   * 重启 Actor
   * @param reason 重启原因
   */
  private restartActor(reason: Error): void {
    try {
      // 创建新Actor实例
      this._actor = this._props.producer();
      
      // 如果新Actor实现了postRestart，调用它
      const extendedActor = this._actor as ExtendedActor;
      if (extendedActor.postRestart) {
        extendedActor.postRestart();
      }
      
      // 发布重启事件
      this.eventStream.publish(new Events.ActorRestarted(this._self, reason));
    } catch (error) {
      console.error(`Failed to restart actor ${this._self.id}:`, error);
      this.stop(this._self);
    }
  }

  private processMessages(): void {
    // Process system messages first
    while (!this.systemMessageQueue.isEmpty()) {
      const message = this.systemMessageQueue.dequeue();
      if (message && typeof message === 'object' && 'actor' in message) {
        const { actor, message: msg } = message as { actor: ExtendedActor; message: any };
        this._dispatcher.schedule(() => {
          this.invokeSystemMessage(actor, msg);
        });
      }
    }

    // Then process user messages
    while (!this.messageQueue.isEmpty()) {
      const message = this.messageQueue.dequeue();
      if (message && typeof message === 'object' && 'actor' in message) {
        const { actor, message: msg } = message as { actor: ExtendedActor; message: any };
        this._dispatcher.schedule(() => {
          this.invokeUserMessage(actor, msg);
        });
      }
    }
  }

  private getActorByPID(pid: PID): ExtendedActor | undefined {
    // This is a placeholder implementation
    // In a real system, you would look up the actor in your actor registry
    return undefined;
  }

  private stopActor(actor: ExtendedActor): void {
    // Clear message queues for this actor
    const actorId = actor.pid?.id;
    if (actorId) {
      // Only clear messages for this actor
      const newMessageQueue = new DefaultMessageQueue();
      const newSystemMessageQueue = new DefaultMessageQueue();
      
      while (!this.messageQueue.isEmpty()) {
        const msg = this.messageQueue.dequeue();
        if (msg && typeof msg === 'object' && 'actor' in msg) {
          const { actor: msgActor, message } = msg as { actor: ExtendedActor; message: any };
          if (msgActor.pid?.id !== actorId) {
            newMessageQueue.enqueue(msg);
          }
        }
      }
      
      while (!this.systemMessageQueue.isEmpty()) {
        const msg = this.systemMessageQueue.dequeue();
        if (msg && typeof msg === 'object' && 'actor' in msg) {
          const { actor: msgActor, message } = msg as { actor: ExtendedActor; message: any };
          if (msgActor.pid?.id !== actorId) {
            newSystemMessageQueue.enqueue(msg);
          }
        }
      }
      
      this.messageQueue = newMessageQueue;
      this.systemMessageQueue = newSystemMessageQueue;
    }

    // Publish stop event
    if (actor.pid) {
      this.eventStream.publish(new Events.ActorStopped(actor.pid));
    }

    if (actor.postStop) {
      actor.postStop();
    }
  }

  registerActor(actor: ExtendedActor, pid: PID): void {
    actor.pid = pid;
    this.actorMap.set(pid.id, actor);
  }
} 